<?php
declare(strict_types=1);

namespace Zyucv7\Core\Error\Handler;

use Zyucv7\Core\Error\IHandler;
use Zyucv7\Core\Error\Log AS ErrorLog;

/**
 * @description 错误处理实现类
 * @package Zyucv7\Core\Error
 */
class Error implements IHandler
{

    /**
     * 获取错误类型字符串
     * @param int $errno
     * @return string
     */
    private static function getErrorType($errno)
    {
        $types = [
            E_ERROR => 'E_ERROR',
            E_WARNING => 'E_WARNING',
            E_PARSE => 'E_PARSE',
            E_NOTICE => 'E_NOTICE',
            E_CORE_ERROR => 'E_CORE_ERROR',
            E_CORE_WARNING => 'E_CORE_WARNING',
            E_COMPILE_ERROR => 'E_COMPILE_ERROR',
            E_COMPILE_WARNING => 'E_COMPILE_WARNING',
            E_USER_ERROR => 'E_USER_ERROR',
            E_USER_WARNING => 'E_USER_WARNING',
            E_USER_NOTICE => 'E_USER_NOTICE',
            E_STRICT => 'E_STRICT',
            E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
            E_DEPRECATED => 'E_DEPRECATED',
            E_USER_DEPRECATED => 'E_USER_DEPRECATED'
        ];
        return $types[$errno] ?? 'UNKNOWN';
    }

    /**
     * @description 错误处理
     * @param \Throwable $e
     */
    public function handle($errno, $errstr, $errfile, $errline, $errcontext = []): void {

        $errorType = $this->getErrorType($errno);
        
        // $logData = [
        //     'timestamp' => date('Y-m-d H:i:s'),
        //     'type' => 'ERROR',
        //     'level' => $errorType,
        //     'code' => $errno,
        //     'message' => $errstr,
        //     'file' => $errfile,
        //     'line' => $errline,
        //     'context' => $errcontext,
        //     'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
        // ];
        $logData = [
            'timestamp' => time(),
            'message' => $errstr,
            'file' => $errfile,
            'line' => $errline,
        ];
        
        ErrorLog::error($logData);

        // 如果是致命错误，终止执行
        if ($errno === E_ERROR || $errno === E_USER_ERROR) {
            exit(1);
        }
    }

    /**
     * 脚本终止处理器
     * 用于捕获致命错误 (E_ERROR)
     */
    public function handleShutdown()
    {
        $error = error_get_last();

        // 仅处理致命错误
        if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE])) {
            $this->handle($error['type'], $error['message'], $error['file'], $error['line']);
        }
    }

    /**
     * @description 注册错误处理
     * @param \Throwable $e
     */
    public function register(): void
    {
        // 设置错误处理器
        set_error_handler([$this, 'handle'], E_ALL);

        // 注册一个在脚本终止时执行的函数，用于捕获致命错误
        register_shutdown_function([$this, 'handleShutdown']);
    }
}